#include "Globals.h"
#include "ifont.h"

//--------------------------------------------------------------------------------
//	initialize a font asset
//--------------------------------------------------------------------------------
void *ITextFont::AssetInit( IAssetFile *pi, const CMasterIndexEntry *pme, void *context )
{
	ITextFont	*ret;

	ret = (ITextFont*)pi->GetChunk(pme->nameHash,pme->primaryChunk);
	if( ret )
	{
		ret->pChars = (SFontChar*)pi->GetChunk(pme->nameHash,*(LOCID*)&ret->pChars);
	}
	return (void*)ret;
}

//--------------------------------------------------------------------------------
//	uninitialize a font asset
//--------------------------------------------------------------------------------
void ITextFont::AssetUninit( void *ptr, void *context )
{
}


//--------------------------------------------------------------------------------
//	fixup an asset
//--------------------------------------------------------------------------------
void ITextFont::AssetFixup( CAssetFileMgr *pMgr, const IAssetFile *pFile, void *ptr, const CMasterIndexEntry *pEntry )
{
	ITextFont	*pFont = (ITextFont*)ptr;

	// fix font texture
	if( pFont->pTexture==0 )
		pFont->pTexture = (ITexture*)pMgr->FindAsset(pFont->textureName,"TEXTURE");
}

//--------------------------------------------------------------------------------
//	find a character in a font
//	use a binary search
//--------------------------------------------------------------------------------
const SFontChar	*ITextFont::FindChar( unicode character ) const
{
	s32		window[3];

	window[0] = 0;
	window[2] = ((s32)numChars)-1;

	while( window[0]<=window[2] )
	{
		window[1] = (window[0]+window[2])/2;

		if( pChars[window[1]].character==character )
			return &pChars[window[1]];

		if( pChars[window[1]].character>character )
			window[2] = window[1]-1;
		else
			window[0] = window[1]+1;
	}
	return 0;
}

//--------------------------------------------------------------------------------
//	get the size of a piece of text
//--------------------------------------------------------------------------------
void ITextFont::GetTextSize( const unicode *ptr, float outSize[2], f32 iFontSize, f32 aspect ) const
{
	unicode			c;
	f32				scale;
	f32				lineWidth;
	const SFontChar	*pChar;

	outSize[0] = outSize[1] = 0;
	if( ptr==0 )
		return;

	lineWidth  = 0;

	scale = iFontSize/((f32)fontSize);
	while( c=*(ptr++) )
	{
		if( c<=L' ' )
		{
			if( c==L' ' )
			{
				lineWidth += iFontSize*0.25f;	// space character
			}
			else if( c==L'\n' )
			{
				outSize[0]  = Max(outSize[0],lineWidth);
				outSize[1] += iFontSize*aspect;
				lineWidth = 0;
			}
			continue;
		}
		pChar = FindChar(c);
		if( pChar )
		{
			lineWidth += (pChar->preAdvance+pChar->postAdvance)*scale;
		}
	}

	outSize[0]  = Max(outSize[0],lineWidth);
	outSize[1] += iFontSize*aspect;
}

//--------------------------------------------------------------------------------
//	print
//--------------------------------------------------------------------------------
u32 ITextFont::Print( const unicode *ptr, SFontVertex *out, f32 iFontSize, f32 aspect, u32 color, f32 *outSize ) const
{
	f32				curpos[2];
	f32				scale[2];
	f32				size[2];
	unicode			c;
	u32				ret = 0;
	const SFontChar	*pChar;

	if( outSize==0 )
		outSize = size;

	outSize[0] = curpos[0] = curpos[1] = 0;


	if( ptr!=0 )
	{

		scale[0] = iFontSize/((f32)fontSize);
		scale[1] = scale[0]*aspect;
		while( c=*(ptr++) )
		{
			if( c<=L' ' )
			{
				if( c==L' ' )
				{
					curpos[0] += iFontSize*0.25f;	// space character
				}
				else if( c==L'\n' )
				{
					outSize[0] = Max(outSize[0],curpos[0]);
					curpos[0]  = 0.0f;
					curpos[1] += iFontSize*aspect;
				}
				continue;
			}
			pChar = FindChar(c);
			if( pChar )
			{
				curpos[0] += pChar->preAdvance*scale[0];
	
				{
					register f32	x = curpos[0] + pChar->width*scale[0];
					register f32	y = curpos[1] + pChar->height*scale[1];
					register u32	w = pChar->posX + pChar->width;
					register u32	h = pChar->posY + pChar->height;
	
					out[0].xy[0] = curpos[0];
					out[0].xy[1] = curpos[1];
					out[0].uv[0] = pChar->posX;
					out[0].uv[1] = pChar->posY;
					out[0].color = color;
		
					out[1].xy[0] = x;
					out[1].xy[1] = curpos[1];
					out[1].uv[0] = w;
					out[1].uv[1] = pChar->posY;
					out[1].color = color;
		
					out[2].xy[0] = curpos[0];
					out[2].xy[1] = y;
					out[2].uv[0] = pChar->posX;
					out[2].uv[1] = h;
					out[2].color = color;
		
					out[3].xy[0] = x;
					out[3].xy[1] = y;
					out[3].uv[0] = w;
					out[3].uv[1] = h;
					out[3].color = color;
				}
	
				curpos[0] += pChar->postAdvance*scale[0];
	
				out += 4;
				ret++;
			}
		}
	}

	outSize[0] = Max(outSize[0],curpos[0]);
	outSize[1] = curpos[1] + iFontSize*aspect;
	return ret;
}
